<template>
  <div class="app-container">
    <div class="filter-container">
      <el-input
        v-model="listQuery.keyword"
        placeholder="用户名"
        style="width: 200px;"
        class="filter-item"
        @keyup.enter.native="handleFilter"
      />
      <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
        搜索
      </el-button>
      <el-button
        class="filter-item"
        type="primary"
        icon="el-icon-plus"
        @click="handleCreate"
      >
        添加
      </el-button>
      <span v-if="multipleSelection.length > 0" class="selection-info">
        已选择 <span class="selection-count">{{ multipleSelection.length }}</span> 条数据
      </span>
    </div>

    <el-table
      v-loading="listLoading"
      :data="list"
      border
      fit
      highlight-current-row
      style="width: 100%;"
      @selection-change="handleSelectionChange"
      class="custom-table"
    >
      <el-table-column
        type="selection"
        width="55"
        align="center"
      />
      <el-table-column label="ID" prop="id" align="center" min-width="60" />
      <el-table-column label="用户名" align="center" min-width="160">
        <template slot-scope="{row}">
          <div>{{ row.username }}</div>
          <div v-if="row.is_superuser" style="margin-top: 4px;">
            <el-tag type="danger" size="mini" style="font-size: 10px;">
              超级管理员
            </el-tag>
          </div>
          <div v-if="row.uid" class="user-info">
            <span class="info-item">UID: {{ row.uid }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="邮箱" prop="email" align="center" min-width="180">
        <template slot-scope="{row}">
          {{ row.email || '-' }}
        </template>
      </el-table-column>
      <el-table-column label="手机号" prop="phone" align="center" min-width="130">
        <template slot-scope="{row}">
          {{ row.phone || '-' }}
        </template>
      </el-table-column>
      <el-table-column label="头像" align="center" min-width="80">
        <template slot-scope="{row}">
          <el-avatar v-if="row.avatar" :src="row.avatar" :size="40"></el-avatar>
          <span v-else>-</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" min-width="160" class-name="small-padding fixed-width">
        <template slot-scope="{row}">
          <el-button type="primary" size="mini" @click="handleUpdate(row)">
            编辑
          </el-button>
          <el-button 
            type="danger" 
            size="mini" 
            :disabled="row.is_superuser"
            @click="handleDelete(row)"
            :title="row.is_superuser ? '不能删除超级管理员' : '删除用户'"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="listQuery.page"
      :limit.sync="listQuery.page_size"
      @pagination="getList"
    />

    <!-- 添加/编辑用户对话框 -->
    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
      <el-form
        ref="dataForm"
        :rules="rules"
        :model="temp"
        label-position="right"
        label-width="100px"
      >
        <el-form-item label="用户名" prop="username">
          <el-input v-model="temp.username" />
          <span class="form-tip">建议使用公司邮箱前缀作为用户名</span>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="temp.email" type="email" />
        </el-form-item>
        <el-form-item label="手机号" prop="phone">
          <el-input v-model="temp.phone" />
        </el-form-item>
        <el-form-item label="头像" prop="avatar">
          <div class="avatar-upload-container">
            <div class="avatar-preview">
              <el-avatar v-if="temp.avatar" :src="temp.avatar" :size="80"></el-avatar>
              <el-avatar v-else :size="80" icon="el-icon-user-solid"></el-avatar>
            </div>
            <div class="upload-controls">
              <input
                ref="avatarInput"
                type="file"
                accept="image/*"
                style="display: none"
                @change="handleFileSelect"
              >
              <el-button size="small" type="primary" icon="el-icon-upload" @click="selectFile">
                {{ temp.avatar ? '更换头像' : '上传头像' }}
              </el-button>
              <div class="upload-tips">
                <p>支持 JPG、PNG、GIF、BMP 格式</p>
                <p>文件大小不超过 5MB</p>
              </div>
            </div>
          </div>
        </el-form-item>
        <el-form-item v-if="dialogStatus==='update'" label="UID" prop="uid">
          <el-input v-model="temp.uid" :disabled="true" />
          <span class="form-tip">用户唯一标识符（系统自动生成）</span>
        </el-form-item>
        <el-form-item label="密码" prop="password" v-if="dialogStatus==='create'">
          <el-input v-model="temp.password" type="password" show-password />
          <span class="form-tip">请使用6位以上密码</span>
        </el-form-item>
        <el-form-item v-else label="修改密码" prop="newPassword">
          <el-input v-model="temp.newPassword" type="password" show-password />
          <span class="form-tip">如不修改密码请留空</span>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">
          取消
        </el-button>
        <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
          确认
        </el-button>
      </div>
    </el-dialog>

    <!-- 头像裁剪对话框 -->
    <el-dialog title="裁剪头像" :visible.sync="cropperVisible" width="800px" :close-on-click-modal="false">
      <div class="cropper-container">
        <div class="cropper-main">
          <vue-cropper
            ref="cropper"
            :img="cropperImg"
            :output-size="1"
            :output-type="'png'"
            :info="true"
            :full="false"
            :can-move="true"
            :can-move-box="true"
            :original="false"
            :auto-crop="true"
            :auto-crop-width="200"
            :auto-crop-height="200"
            :fixed="true"
            :fixed-number="[1, 1]"
            :center-box="true"
            :info-true="true"
            :fixed-box="false"
            @real-time="realTime"
          />
        </div>
        <div class="cropper-preview">
          <div class="preview-title">预览</div>
          <div class="preview-box">
            <div :style="previews.div" class="preview">
              <img :src="previews.url" :style="previews.img">
            </div>
          </div>
          <div class="preview-info">
            <p>建议尺寸：200x200像素</p>
            <p>支持格式：JPG、PNG、GIF、BMP</p>
          </div>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancelCrop">取消</el-button>
        <el-button type="primary" @click="confirmCrop" :loading="cropLoading">确认上传</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { fetchList, createUser, updateUser, deleteUser, uploadAvatar } from '@/api/user'
import Pagination from '@/components/Pagination'
import { getToken } from '@/utils/auth'
import { VueCropper } from 'vue-cropper'

export default {
  name: 'UserManagement',
  components: { 
    Pagination,
    VueCropper
  },
  data() {
    const sanitizeInput = (value) => {
      if (!value) return value
      // 过滤特殊字符，防止 SQL 注入和 XSS 攻击
      return value.replace(/[<>'";\\/]/g, '')
    }

    return {
      list: null,
      total: 0,
      listLoading: true,
      listQuery: {
        page: 1,
        page_size: 20,
        keyword: undefined
      },
      temp: {
        id: undefined,
        username: '',
        email: '',
        phone: '',
        avatar: '',
        uid: '',
        password: '',
        newPassword: ''
      },
      dialogFormVisible: false,
      dialogStatus: '',
      textMap: {
        update: '编辑用户',
        create: '添加用户'
      },
      rules: {
        username: [
          { required: true, message: '用户名不能为空', trigger: 'blur' },
          { min: 3, max: 20, message: '用户名长度在 3 到 20 个字符', trigger: 'blur' },
          { validator: (rule, value, callback) => {
            const sanitized = sanitizeInput(value)
            if (sanitized !== value) {
              callback(new Error('用户名包含非法字符'))
            } else {
              callback()
            }
          }, trigger: 'blur' }
        ],
        email: [
          { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] },
          { validator: (rule, value, callback) => {
            if (value) {
              const sanitized = sanitizeInput(value)
              if (sanitized !== value) {
                callback(new Error('邮箱包含非法字符'))
              }
            }
            callback()
          }, trigger: 'blur' }
        ],
        phone: [
          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' },
          { validator: (rule, value, callback) => {
            if (value) {
              const sanitized = sanitizeInput(value)
              if (sanitized !== value) {
                callback(new Error('手机号包含非法字符'))
              }
            }
            callback()
          }, trigger: 'blur' }
        ],
        password: [
          { required: true, message: '密码不能为空', trigger: 'blur' },
          { min: 6, message: '密码长度不能少于6位', trigger: 'blur' }
        ]
      },
      multipleSelection: [],
      cropperVisible: false,
      cropperImg: '',
      previews: {
        div: {
          width: '100%',
          height: 'auto',
          overflow: 'hidden',
          borderRadius: '4px',
          backgroundColor: '#fff'
        },
        img: {
          width: '100%',
          height: 'auto',
          objectFit: 'cover'
        },
        url: ''
      },
      cropLoading: false
    }
  },
  created() {
    this.getList()
  },
  methods: {
    getList() {
      this.listLoading = true
      fetchList(this.listQuery).then(response => {
        if (response.code === 200) {
          this.list = response.data.results
          this.total = response.data.count
        } else {
          this.$message.error(response.message || '获取用户列表失败')
        }
        this.listLoading = false
      }).catch(error => {
        console.error('获取用户列表失败:', error)
        this.$message.error('获取用户列表失败')
        this.listLoading = false
      })
    },
    handleFilter() {
      this.listQuery.page = 1
      this.getList()
    },
    resetTemp() {
      this.temp = {
        id: undefined,
        username: '',
        email: '',
        phone: '',
        avatar: '',
        uid: '',
        password: '',
        newPassword: ''
      }
    },
    handleCreate() {
      this.resetTemp()
      this.dialogStatus = 'create'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleUpdate(row) {
      this.temp = Object.assign({}, row)
      this.temp.password = ''
      this.temp.newPassword = ''
      this.dialogStatus = 'update'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleSelectionChange(val) {
      this.multipleSelection = val
    },
    handleDelete(row) {
      // 检查是否为超级管理员
      if (row.is_superuser) {
        this.$message.warning('不能删除超级管理员用户')
        return
      }
      
      this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteUser(row.id).then(() => {
          this.getList()
          this.$message.success('删除成功')
        }).catch(() => {
          this.$message.error('删除失败')
        })
      })
    },
    createData() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          createUser(this.temp).then(() => {
            this.getList()
            this.dialogFormVisible = false
            this.$notify({
              title: '成功',
              message: '创建成功',
              type: 'success',
              duration: 2000
            })
          })
        }
      })
    },
    updateData() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          const tempData = Object.assign({}, this.temp)
          // 不需要删除newPassword字段，让后端序列化器处理
          // 如果newPassword为空，后端会忽略密码更新
          
          updateUser(tempData).then(() => {
            this.getList()
            this.dialogFormVisible = false
            this.$notify({
              title: '成功',
              message: '更新成功',
              type: 'success',
              duration: 2000
            })
          })
        }
      })
    },
    handleFileSelect(event) {
      const file = event.target.files[0]
      if (file) {
        // 验证文件
        if (this.beforeAvatarUpload(file)) {
          // 显示裁剪弹窗
          const reader = new FileReader()
          reader.onload = (e) => {
            this.cropperImg = e.target.result
            this.cropperVisible = true
          }
          reader.readAsDataURL(file)
        }
      }
      // 清空input值，允许重复选择同一文件
      event.target.value = ''
    },
    selectFile() {
      this.$refs.avatarInput.click()
    },
    realTime(data) {
      this.previews = data
    },
    cancelCrop() {
      this.cropperVisible = false
      this.cropperImg = ''
    },
    async confirmCrop() {
      this.cropLoading = true
      try {
        // 获取裁剪后的图片blob
        const blob = await new Promise((resolve) => {
          this.$refs.cropper.getCropBlob((blob) => {
            resolve(blob)
          })
        })
        
        // 创建FormData并上传
        const formData = new FormData()
        formData.append('avatar', blob, 'avatar.png')
        
        // 使用API方法上传
        const response = await uploadAvatar(this.temp.id, formData)
        
        this.cropLoading = false
        if (response.code === 200) {
          this.temp.avatar = response.data.avatar
          this.$message.success('头像上传成功')
          this.cropperVisible = false
          this.getList() // 刷新列表
        } else {
          this.$message.error(response.message || '头像上传失败')
        }
      } catch (error) {
        this.cropLoading = false
        console.error('头像上传失败:', error)
        this.$message.error('头像上传失败，请重试')
      }
    },
    beforeAvatarUpload(file) {
      const isValidType = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp'].includes(file.type)
      const isLt5M = file.size / 1024 / 1024 < 5

      if (!isValidType) {
        this.$message.error('上传头像图片只能是 JPG、PNG、GIF、BMP 格式!')
      }
      if (!isLt5M) {
        this.$message.error('上传头像图片大小不能超过 5MB!')
      }
      return isValidType && isLt5M
    }
  }
}
</script>

<style lang="scss">
@import '@/styles/dialog-common.scss';

.filter-container {
  padding: 20px;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 15px;
  margin-bottom: 20px;

  /* 响应式设计 */
  @media screen and (max-width: 768px) {
    padding: 15px;
    gap: 10px;
    
    .filter-item {
      flex: 1;
      min-width: 120px;
    }
    
    .el-input {
      width: 100% !important;
    }
  }

  @media screen and (max-width: 480px) {
    padding: 10px;
    gap: 8px;
    
    .filter-item {
      width: 100%;
      min-width: auto;
    }
    
    .selection-info {
      margin-left: 0;
      margin-top: 5px;
      width: 100%;
      text-align: center;
    }
  }
}

.filter-item {
  margin: 0;
}

.selection-info {
  margin-left: auto;
  font-size: 12px;
  color: #666;
}

.selection-count {
  font-weight: bold;
  color: #409EFF;
  margin: 0 4px;
}

/* 特定于用户管理的样式 */
.form-tip {
  font-size: 12px;
  color: #909399;
  line-height: 1.2;
  padding-top: 4px;
  display: inline-block;
  margin-left: 10px;
}

.user-info {
  margin-top: 5px;
  font-size: 12px;
  color: #666;

  .info-item {
    margin-right: 8px;
    &:not(:last-child):after {
      content: '|';
      margin-left: 8px;
      color: #dcdfe6;
    }
  }
}

.fs-info {
  font-size: 12px;
  color: #666;

  .info-item {
    margin-bottom: 3px;
  }
}

/* 表格容器样式 */
.custom-table {
  width: 100%;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  margin-bottom: 20px;

  /* 确保表格自适应 */
  ::v-deep .el-table {
    width: 100% !important;
  }

  /* 表头样式 */
  ::v-deep .el-table__header-wrapper {
    background-color: #f5f7fa;
  }

  ::v-deep .el-table__header th {
    background-color: #f5f7fa;
    color: #606266;
    font-weight: 600;
    height: 50px;
    padding: 8px 0;
  }

  /* 表格主体样式 */
  ::v-deep .el-table__body td {
    padding: 12px 0;
  }

  /* 悬停效果 */
  ::v-deep .el-table--enable-row-hover .el-table__body tr:hover > td {
    background-color: #f5f7fa;
  }

  /* 响应式设计 */
  @media screen and (max-width: 1200px) {
    ::v-deep .el-table__header th,
    ::v-deep .el-table__body td {
      padding: 8px 4px;
      font-size: 13px;
    }
    
    ::v-deep .el-button--mini {
      padding: 5px 8px;
      font-size: 11px;
    }
  }

  @media screen and (max-width: 768px) {
    ::v-deep .el-table__header th,
    ::v-deep .el-table__body td {
      padding: 6px 2px;
      font-size: 12px;
    }
    
    ::v-deep .el-button--mini {
      padding: 4px 6px;
      font-size: 10px;
    }
    
    ::v-deep .el-avatar {
      width: 32px !important;
      height: 32px !important;
    }
    
    ::v-deep .el-tag--mini {
      font-size: 9px;
      padding: 0 4px;
    }
  }

  @media screen and (max-width: 480px) {
    ::v-deep .el-table__header th,
    ::v-deep .el-table__body td {
      padding: 4px 1px;
      font-size: 11px;
    }
    
    ::v-deep .el-button--mini {
      padding: 3px 5px;
      font-size: 9px;
    }
  }
}

.avatar-upload-container {
  display: flex;
  align-items: center;
  gap: 10px;
}

.avatar-preview {
  width: 80px;
  height: 80px;
  border-radius: 4px;
  overflow: hidden;
  background-color: #f5f7fa;
}

.upload-controls {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.upload-tips {
  margin-top: 5px;
  font-size: 12px;
  color: #909399;
}

/* 图片裁剪器样式 */
.cropper-container {
  display: flex;
  gap: 20px;
  height: 400px;
}

.cropper-main {
  flex: 1;
  height: 100%;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
}

.cropper-preview {
  width: 200px;
  display: flex;
  flex-direction: column;
}

.preview-title {
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 10px;
  color: #303133;
}

.preview-box {
  width: 100%;
  height: 200px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 15px;
  background-color: #f5f7fa;
  display: flex;
  align-items: center;
  justify-content: center;
}

.preview {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.preview-info {
  font-size: 12px;
  color: #909399;
  line-height: 1.5;
}

.preview-info p {
  margin: 0 0 5px 0;
}
</style> 